如何将字符串变量转换为数值变量?
By Ruben Geert van den Berg 发表于 SPSS 博客
介绍 & 练习数据文件
将 SPSS 中的 字符串变量 转换为数值变量很简单。但是,有一个巨大的陷阱,很少有人意识到:无法转换为数字的字符串值会导致 系统缺失值 (system missing values),而 SPSS 不会抛出任何错误或警告。
这可能会破坏您的数据,而您却毫不知情。不相信吗?我将在 convert-strings.sav 上演示这个问题以及解决方案,部分内容如下所示。
SPSS 字符串转数值 - 错误的方式
首先,您_可以_在 变量视图 (variable view) 中将字符串转换为数值变量,如下所示。
现在,我从不使用这种方法,因为:
- 我无法一次应用于多个变量,因此可能需要比必要更多的精力;
- 它不会生成任何 语法 (syntax):没有 P aste 按钮,也没有任何内容附加到我的日志文件中;
- 它可能会破坏数据。 但是,有补救措施。
问题是什么?
好吧,让我们_做_而不是阅读它。我们将:
- 将空单元格设置为
s3
的 用户缺失值 (user missing values); - 在变量视图中将
s3
转换为数值; - 对结果运行描述性统计。
*** 将空字符串设置为 s3 的用户缺失值。
MISSING VALUES s3 ('').
*** 检查 s3 的频率表。
FREQUENCIES s3.
*** 现在在变量视图下手将 s3 手动转换为数值。
*** 检查结果。
DESCRIPTIVES s3.
*** N = 444 而不是 459。也就是说,15 个值转换失败,我们不知道为什么。
结果
请注意,我们的字符串变量中的某些值已用 “a” 标记。我们可能希望将这些值转换为数字。我们有 459 个有效值(非空单元格)。
将变量转换为数值后,我们运行了一些描述性统计。请注意,我们只有 N = 444。显然,15 个值转换失败 - 可能不是我们想要的。并且我们通常不会注意到这个问题,因为我们没有收到任何警告或错误。
转换失败 - 最简单的解决方案
好的,那么我们如何才能安全地执行转换?好吧,我们只需要:
- 检查频率表:转换前我们有多少个非空值?
- 将我们的变量转换为数值;
- 在转换后检查描述性统计中的 N。如果 N 低于非空字符串值的数量(转换前的频率),那么可能存在问题。
在我们的第一个示例中,频率表已经表明我们必须在转换变量之前从所有值中删除 “a”。我们将在稍后这样做。 虽然安全,但我仍然认为这种方法太麻烦,尤其是对于多个变量。让我们使用一些方便的语法来加快速度。
SPSS - 使用语法将字符串转换为数值
将字符串变量转换为数值变量的最快方法是使用 ALTER TYPE 命令。 这需要 SPSS 版本 16 或更高版本。 对于 SPSS 15 或更低版本,请使用 NUMBER 函数。 它允许我们用一行语法转换多个变量。 下面的语法一次性转换所有字符串变量。 然后我们检查描述性统计表。 如果我们没有任何系统缺失值,我们就完成了。
SPSS ALTER TYPE 示例
*** 关闭数据而不保存,然后在继续之前重新打开。
*** 一次转换所有变量。
ALTER TYPE s1 TO s3 (f1) s4 (f6.3).
*** 检查描述性统计。
DESCRIPTIVES s1 TO s4.
注意:使用 ALTER TYPE s1 TO s4 (f1).
也可以,但 s4 的小数位数将不可见。 这就是我们设置正确的 f 格式的原因:f6.3
表示 6 个字符,包括小数分隔符和 3 个小数位,如 12.345。 这是我们字符串值的格式。
结果
由于我们的数据中有 480 个案例,因此我们完成了 s1
。 但是,其他 3 个变量包含系统缺失值,因此我们需要找出原因。 由于我们无法撤消该操作,因此请关闭数据而不保存并重新打开它。
解决方案 2:在转换之前复制字符串变量
现在事情变得有点技术性了。 但是,努力学习的读者将学习一种非常有效的解决方案,该解决方案也适用于许多其他情况。 我们基本上会
- 复制所有字符串变量;
- 转换所有字符串变量;
- 将原始变量与转换后的变量进行比较。
准确地说,我们将标记在转换后为系统缺失值的非空字符串值。 由于这些至少是可疑的,因此我们将这些称为转换失败。 这听起来可能令人生畏,但是如果我们使用正确的命令组合,这是完全可行的。 这些主要是 STRING, RECODE, DO REPEAT 和 IF。
复制并转换多个字符串变量
*** 关闭数据而不保存,然后在继续之前重新打开。
*** 复制所有字符串变量。
STRING c1 TO c4 (A7).
RECODE s1 TO s4 (ELSE = COPY) INTO c1 TO c4.
*** 将变量转换为数值。
ALTER TYPE s1 TO s3 (F1) s4 (F6.3).
*** 对于每个变量,标记转换失败:转换后的值为系统缺失值,但原始值不为空的情况。
DO REPEAT #conv = s1 TO s4 / #ori = c1 TO c4 / #flags = flag1 TO flag4.
IF(SYSMIS(#conv) AND #ori <> ' ') #flags = 1.
END REPEAT.
*** 如果 N > 0,则某些变量发生了转换失败。
DESCRIPTIVES flag1 TO flag4.
结果
只有 flag3
和 flag4
包含一些转换失败。 我们可以通过将这些案例移动到数据集的顶部来直观地检查问题所在。
*** 直观地检查值无法转换的原因。
SORT CASES BY flag3 (D).
*** 一些值用“a”标记。
SORT CASES BY flag4 (D).
*** 一些值用“a”到“e”标记。
结果
删除非法字符,复制和转换
某些值用字母 “a” 到 “e” 标记,这就是它们无法转换的原因。 我们现在将解决该问题。 首先,我们关闭数据而不保存并重新打开它。 然后,我们重新运行之前的语法,但在转换之前删除这些字母。
语法
*** 关闭数据而不保存,然后在继续之前重新打开。
*** 复制所有字符串变量。
STRING c1 TO c4 (A7).
RECODE s1 TO s4 (ELSE = COPY) INTO c1 TO c4.
*** 从 s3 中删除“a”。
COMPUTE s3 = REPLACE(s3,'a','').
*** 从 s4 中删除“a”到“e”。
DO REPEAT #char = 'a' 'b' 'c' 'd' 'e'.
COMPUTE s4 = REPLACE(s4,#char,' ').
END REPEAT.
*** 尝试再次转换变量。
ALTER TYPE s1 TO s3 (F1) s4 (F6.3).
*** 再次标记转换失败。
DO REPEAT #conv = s1 TO s4 / #ori = c1 TO c4 / #flags = flag1 TO flag4.
IF(SYSMIS(#conv) AND #ori <> ' ') #flags = 1.
END REPEAT.
*** 检查转换是否成功。
DESCRIPTIVES flag1 TO flag4.
*** 所有 flag 变量的 N = 0,因此我们完成了。
*** 删除复制的变量和 flag 变量。
DELETE VARIABLES c1 TO flag4.
结果
所有 flag 变量都仅包含(系统)缺失值。 这意味着我们不再有任何转换失败; 所有变量都已正确转换。 我们现在可以删除所有副本和标志变量,保存我们的数据并继续。 感谢您的阅读!